Skip to content

Add new integration for AiDot#167272

Open
s1eedz wants to merge 85 commits intohome-assistant:devfrom
s1eedz:feature/aidot-wifi-lights-improve
Open

Add new integration for AiDot#167272
s1eedz wants to merge 85 commits intohome-assistant:devfrom
s1eedz:feature/aidot-wifi-lights-improve

Conversation

@s1eedz
Copy link
Copy Markdown

@s1eedz s1eedz commented Apr 3, 2026

Breaking change

Proposed change

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • I understand the code I am submitting and can explain how it works.
  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.
  • Any generated code has been carefully reviewed for correctness and compliance with project standards.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies a diff between library versions and ideally a link to the changelog/release notes is added to the PR description.

To help with the load of incoming pull requests:

Copilot AI review requested due to automatic review settings April 7, 2026 05:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 20 changed files in this pull request and generated 3 comments.

Comment thread homeassistant/components/aidot/light.py Outdated

from .const import DOMAIN

type AidotConfigEntry = ConfigEntry[AidotDeviceManagerCoordinator]
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type alias definition using the type keyword (line 27) requires Python 3.12+. Home Assistant typically needs to support Python 3.11+, so this should use TypeAlias from typing instead: AidotConfigEntry: TypeAlias = ConfigEntry[AidotDeviceManagerCoordinator]

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 7, 2026 05:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 20 changed files in this pull request and generated 2 comments.

Comment thread homeassistant/components/aidot/light.py Outdated
Comment thread homeassistant/components/aidot/coordinator.py Outdated
s1eedz and others added 2 commits April 7, 2026 13:52
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 7, 2026 05:54
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 18 out of 20 changed files in this pull request and generated 3 comments.

Comment on lines +39 to +44
def mock_setup_entry() -> Generator[AsyncMock]:
"""Override async_setup_entry."""
with patch(
"homeassistant.components.aidot.async_setup_entry", return_value=True
) as mock_setup_entry:
yield mock_setup_entry
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type hint for the mock_setup_entry fixture is incorrect. The fixture yields a MagicMock (from patch()), not an AsyncMock. The return type should be Generator[MagicMock, None, None].

Copilot uses AI. Check for mistakes.
Comment thread homeassistant/components/aidot/light.py Outdated
Comment on lines +45 to +59
if added_device_ids:
async_add_entities(
AidotLight(hass, coordinator.device_coordinators[device_id])
for device_id in added_device_ids
)
lists_added |= added_device_ids
elif lists_added - new_lists:
removed_device_ids = lists_added - new_lists
for device_id in removed_device_ids:
entity_registry = er.async_get(hass)
if entity := entity_registry.async_get_entity_id(
"light", DOMAIN, device_id
):
entity_registry.async_remove(entity)
lists_added = lists_added - removed_device_ids
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The add_entities callback uses elif (line 51) to check for removed devices, but it should use a separate if statement. Currently, if devices are both added and removed in the same update, only the added devices will be processed and the removed devices will be ignored. This should be an independent if statement, not elif.

Copilot uses AI. Check for mistakes.
Comment thread tests/components/aidot/test_light.py
Copilot AI review requested due to automatic review settings April 7, 2026 09:42
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 20 changed files in this pull request and generated 3 comments.

Comment on lines +125 to +145
async def async_turn_on(self, **kwargs: Any) -> None:
"""Fix brightness state synchronization by updating the coordinator's `dimming` field."""
if ATTR_BRIGHTNESS in kwargs:
brightness = kwargs.get(ATTR_BRIGHTNESS, 255)
await self.coordinator.device_client.async_set_brightness(brightness)
self.coordinator.data.dimming = brightness
elif ATTR_COLOR_TEMP_KELVIN in kwargs:
color_temp_kelvin = kwargs.get(ATTR_COLOR_TEMP_KELVIN)
await self.coordinator.device_client.async_set_cct(color_temp_kelvin)
self.coordinator.data.cct = color_temp_kelvin
self._attr_color_mode = ColorMode.COLOR_TEMP
elif ATTR_RGBW_COLOR in kwargs:
rgbw_color = kwargs.get(ATTR_RGBW_COLOR)
await self.coordinator.device_client.async_set_rgbw(rgbw_color)
self.coordinator.data.rgbw = rgbw_color
self._attr_color_mode = ColorMode.RGBW
else:
await self.coordinator.device_client.async_turn_on()

self.coordinator.data.on = True
self._attr_is_on = True
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The async_turn_on and async_turn_off methods directly modify self.coordinator.data attributes instead of using the coordinator's async_set_updated_data method. This bypasses the coordinator's update mechanism and can lead to state synchronization issues. Consider using async_set_updated_data to update the data properly.

Copilot uses AI. Check for mistakes.
Comment on lines +115 to +117
delete_lists = self.previous_lists - (
current_lists := {device[CONF_ID] for device in filter_device_list}
)
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code accesses device[CONF_ID] on line 116 without checking if the key exists, but uses device.get(CONF_ID) on line 127. This is inconsistent. If a device lacks CONF_ID, line 116 will raise a KeyError. Either use consistent error handling or verify that CONF_ID is always present in devices returned from the API.

Copilot uses AI. Check for mistakes.
device
for device in data[CONF_DEVICE_LIST]
if (
device[CONF_TYPE] == "light"
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 109 accesses device[CONF_TYPE] without checking if the key exists, potentially raising a KeyError. Consider using device.get(CONF_TYPE) with a default value or adding validation to ensure devices returned from async_get_all_device() always contain required fields.

Suggested change
device[CONF_TYPE] == "light"
device.get(CONF_TYPE) == "light"

Copilot uses AI. Check for mistakes.
Comment on lines +35 to +36
await self.async_set_unique_id(client.get_identifier())
self._abort_if_unique_id_configured()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we have something more specific like a user ID? Do we get a token back that we can get the user ID out of?

Comment thread homeassistant/components/aidot/light.py Outdated
Comment on lines +35 to +46
@callback
def add_entities() -> None:
"""Add light entities."""
nonlocal lists_added
new_lists = {
device_coordinator.device_client.device_id
for device_coordinator in coordinator.device_coordinators.values()
}

if new_lists - lists_added:
async_add_entities(
AidotLight(hass, coordinator.device_coordinators[device_id])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's a nice feature, we even consider that a good practice, but I also think that adding this in this PR will add an extra review burden, so if we can remove it from this PR and add it in a later PR, we can speed up the review

Comment thread homeassistant/components/aidot/light.py Outdated
@@ -0,0 +1,11 @@
{
"domain": "aidot",
"name": "AiDot Lights Local",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does that work, can you elaborate on that?

But when there's no integration already, we just call it the name of the brand, not appending Local. And unless the company is called AiDot Lights, I would just go with AiDor

Comment thread homeassistant/components/aidot/coordinator.py Outdated
@home-assistant home-assistant bot marked this pull request as draft April 7, 2026 10:33
@s1eedz s1eedz marked this pull request as ready for review April 8, 2026 00:56
Copilot AI review requested due to automatic review settings April 8, 2026 00:56
@home-assistant home-assistant bot requested a review from joostlek April 8, 2026 00:56
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 20 changed files in this pull request and generated 1 comment.

Comment on lines +56 to +57
manufacturer = model_id.split(".")[0]
model = model_id[len(manufacturer) + 1 :]
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The model_id parsing assumes the model_id always contains at least one dot. If a device's model_id doesn't match the expected format (e.g., "aidot.light.rgbw"), the extracted model name could be empty or incorrect. Consider adding validation to handle edge cases or use a more robust parsing method like rsplit with maxsplit parameter.

Suggested change
manufacturer = model_id.split(".")[0]
model = model_id[len(manufacturer) + 1 :]
if "." in model_id:
manufacturer, model = model_id.rsplit(".", 1)
else:
manufacturer = model_id
model = model_id

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants